#include "client.h"


struct sockaddr_in UDP_init(int port_num, char const *IP_addr,int* UDP_fd)
{
    struct sockaddr_in serveraddr;
    int soc = socket(AF_INET, SOCK_DGRAM, 0);
    if (-1 == soc)
    {
        ERRLOG("UDP socket error");
        return serveraddr;
    }
    
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(port_num);                 // 端口号
    serveraddr.sin_addr.s_addr = inet_addr(IP_addr);       // ip地址
   

    *UDP_fd = soc;
    return serveraddr;
}

user_t Login_menu_2(int UDP_fd , struct sockaddr_in serveraddr)
{
    const wchar_t *menu_items[] = {L"登录", L"注册", L"找回密码", L"退出"}; 
    const wchar_t *title = L"你孤独吗？这里有一群热情、团结的朋友等着你"; 
    int num_items = sizeof(menu_items) / sizeof(menu_items[0]);  
    int title_size=sizeof(title);
    user_t userinfo;
    int res;
    while (1)
    {
        res= Login_menu_1(0,menu_items,num_items,title,title_size);
        switch (res)
        {
        case 0:
        //登录
            userinfo = sendLoginRequest(UDP_fd , serveraddr) ;
            //登录请求发送
            text_center("登录成功",RED);
            sleep(2);
            return userinfo ;

        case 1:
        //注册
            userinfo = sign_in();
            if ( !sendSignRequest(UDP_fd , serveraddr , userinfo))
            {
                ERRLOG("注册失败");
                text_center("注册失败",RED);
            }
            else
            {
                center_char("您的账号已经注册成功",RED);
            }
            sleep(2);
            break;
        case 2:
        //找回密码
            retrieve_pass(UDP_fd , serveraddr);
            break;
        
        
        case 3:
            //退出

            exit(-1);

        default:
            break;
        }



    }
    
}   
//登录请求发送
user_t  sendLoginRequest(int UDP_fd , struct sockaddr_in serveraddr)
{
     
    for (size_t i = 0; i < 3; i++)
    {
        user_t info = user_info();
        UDP_data datapack;
        memset(&datapack, 0, sizeof(datapack));
        datapack.SYN = 4; // 登录
        strcpy(datapack.name, "客户端");
        sprintf(datapack.data, "姓名:%s 账号:%s 密码:%s 手机号:%s 性别:%s 等级:%d ", info.name , info.account, info.passwd ,info.phone ,info.sex ,info.status );
        time_t current_time;
        time(&current_time);
        struct tm *local_time = localtime(&current_time);
        strftime(datapack.time, sizeof(datapack.time), "%m/%d %H:%M:%S", local_time);
        datapack.size_num = strlen(datapack.data);
        printf(">>>>>|%d|%s|%s|%d|%s|\n", datapack.SYN, datapack.name, datapack.data, datapack.size_num, datapack.time);
        if (-1 == sendto(UDP_fd, &datapack, sizeof(datapack), 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr)))
        {
            ERRLOG("发送失败\n");
        }
        printf("发送成功\n");
        socklen_t addrlen = sizeof(serveraddr);
        if (-1 == recvfrom(UDP_fd, &datapack, sizeof(datapack), 0, (struct sockaddr *)&serveraddr, &addrlen))
        {
            printf("数据接收失败\n");
        }
        printf(">>>>>|%d|%s|%s|%d|%s|\n", datapack.SYN, datapack.name, datapack.data, datapack.size_num, datapack.time);
        if (datapack.SYN == 4)
        {

            // 解析
            int count = 0;
            size_t j;
            for (size_t i = 0; i < strlen(datapack.data); i++)
            {
                if (datapack.data[i] == ':')
                {
                    count++;

                    switch (count)
                    {
                    case 1:

                        for (j = 0; datapack.data[i + j + 1] != ' '; j++)
                        {
                            info.name[j] = datapack.data[i + j + 1];
                        }
                        info.name[j] = '\0';
                        break;
                    case 2:
                        for (j = 0;datapack.data[i + j + 1] != ' '; j++)
                        {
                            info.account[j] = datapack.data[i + j + 1];
                        }
                        info.account[j] = '\0';
                        break;
                    case 3:
                        for (j = 0;datapack.data[i + j + 1] != ' '; j++)
                        {
                            info.passwd[j] =datapack.data[i + j + 1];
                        }
                        info.passwd[j] = '\0';
                        break;

                    case 4:
                        for (j = 0; datapack.data[i + j + 1] != ' '; j++)
                        {
                            info.phone[j] = datapack.data[i + j + 1];
                        }
                        info.phone[j] = '\0';
                        break;
                    case 5:
                        for (j = 0; datapack.data[i + j + 1] != ' '; j++)
                        {
                            info.sex[j] = datapack.data[i + j + 1];
                        }
                        info.sex[j] = '\0';
                        break;
                    case 6:
                        for (j = 0; datapack.data[i + j + 1] != ' '; j++)
                        {
                            info.status = datapack.data[i + j + 1]-'0';
                        }
                        break;
                    }
                }
            }
            return info;
        }

        text_center("请核对账号密码，然后重写输入",RED);
       
        
    }
    
    printf("超过次数  退出程序\n");
    exit(-1);
   
}

//注册
bool sendSignRequest(int UDP_fd , struct sockaddr_in serveraddr , user_t userinfo)
{

        UDP_data datapack;
        memset(&datapack, 0, sizeof(datapack));
        datapack.SYN = 5; //注册
        strcpy(datapack.name, userinfo.name);
        sprintf(datapack.data, "姓名:%s 账号:%s 密码:%s 手机号:%s 性别:%s 等级:%d ", userinfo.name , userinfo.account, userinfo.passwd ,userinfo.phone ,userinfo.sex ,userinfo.status );
        time_t current_time;
        time(&current_time);
        struct tm *local_time = localtime(&current_time);
        strftime(datapack.time, sizeof(datapack.time), "%m/%d %H:%M:%S", local_time);
        datapack.size_num = strlen(datapack.data);
        printf(">>>>>|%d|%s|%s|%d|%s|\n", datapack.SYN, datapack.name, datapack.data, datapack.size_num, datapack.time);
        if (-1 == sendto(UDP_fd, &datapack, sizeof(datapack), 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr)))
        {
            ERRLOG("发送失败\n");
        }
        printf("发送成功\n");
        socklen_t addrlen = sizeof(serveraddr);
        if (-1 == recvfrom(UDP_fd, &datapack, sizeof(datapack), 0, (struct sockaddr *)&serveraddr, &addrlen))
        {
            printf("数据接收失败\n");
        }
        printf(">>>>>|%d|%s|%s|%d|%s|\n", datapack.SYN, datapack.name, datapack.data, datapack.size_num, datapack.time);
        if (datapack.SYN == 5)
        {

          
           
            return true;
        }
   
    return false;


}

//找回密码

void retrieve_pass(int UDP_fd , struct sockaddr_in serveraddr)
{
    user_t userinfo;
    text_center("请输入姓名：", YELLOW);
    scanf("%s", userinfo.name);
    center_char("请输入需要查找的账号：", YELLOW);
    scanf("%s", userinfo.account);
    center_char("请输入绑定的手机号码：", YELLOW);
    scanf("%s", userinfo.phone);
    center_char("请输入性别：", YELLOW);
    scanf("%s", userinfo.phone);
    strcpy(userinfo.passwd , "0");
    userinfo.status=0;
    UDP_data datapack;
    memset(&datapack, 0, sizeof(datapack));
    datapack.SYN = 6; //找回密码
    strcpy(datapack.name, "客户端");
    sprintf(datapack.data, "姓名:%s 账号:%s 密码:%s 手机号:%s 性别:%s 等级:%d ", userinfo.name , userinfo.account, userinfo.passwd ,userinfo.phone ,userinfo.sex ,userinfo.status );
    time_t current_time;
    time(&current_time);
    struct tm *local_time = localtime(&current_time);
    strftime(datapack.time, sizeof(datapack.time), "%m/%d %H:%M:%S", local_time);
    datapack.size_num = strlen(datapack.data);
    printf(">>>>>|%d|%s|%s|%d|%s|\n", datapack.SYN, datapack.name, datapack.data, datapack.size_num, datapack.time);    //调试
    if (-1 == sendto(UDP_fd, &datapack, sizeof(datapack), 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr)))
    {
        ERRLOG("发送失败\n");
    }
    printf("发送成功\n");   //调试
    socklen_t addrlen = sizeof(serveraddr);
    if (-1 == recvfrom(UDP_fd, &datapack, sizeof(datapack), 0, (struct sockaddr *)&serveraddr, &addrlen))
    {
        printf("数据接收失败\n");
    }
    printf(">>>>>|%d|%s|%s|%d|%s|\n", datapack.SYN, datapack.name, datapack.data, datapack.size_num, datapack.time);    //调试
    
    if (datapack.SYN == 6)
    {

        // 解析
        int count = 0;
        size_t j;
        for (size_t i = 0; i < strlen(datapack.data); i++)
        {
            if (datapack.data[i] == ':')
            {
                count++;

                switch (count)
                {
                case 1:

                    for (j = 0; datapack.data[i + j + 1] != ' '; j++)
                    {
                        userinfo.name[j] = datapack.data[i + j + 1];
                    }
                    userinfo.name[j] = '\0';
                    break;
                case 2:
                    for (j = 0; datapack.data[i + j + 1] != ' '; j++)
                    {
                        userinfo.account[j] = datapack.data[i + j + 1];
                    }
                    userinfo.account[j] = '\0';
                    break;
                case 3:
                    for (j = 0; datapack.data[i + j + 1] != ' '; j++)
                    {
                        userinfo.passwd[j] = datapack.data[i + j + 1];
                    }
                    userinfo.passwd[j] = '\0';
                    break;

                case 4:
                    for (j = 0; datapack.data[i + j + 1] != ' '; j++)
                    {
                        userinfo.phone[j] = datapack.data[i + j + 1];
                    }
                    userinfo.phone[j] = '\0';
                    break;
                case 5:
                    for (j = 0; datapack.data[i + j + 1] != ' '; j++)
                    {
                        userinfo.sex[j] = datapack.data[i + j + 1];
                    }
                    userinfo.sex[j] = '\0';
                    break;
                case 6:
                    for (j = 0; datapack.data[i + j + 1] != ' '; j++)
                    {
                        userinfo.status = datapack.data[i + j + 1] - '0';
                    }
                    break;
                }
            }
        }
        char buff[128];
        sprintf(buff , "%s %s\n" ,"你的账号密码为：" , userinfo.passwd);
        center_char(buff,RED);
        center_char("按任意键返回",YELLOW);
        char buf;
        if (scanf(" %c",&buf))
        {
            return ;
        }
        
    }
}

// 4、下载文件

void download_file(int UDP_fd , struct sockaddr_in serveraddr)
{
    socklen_t addrlen = sizeof(serveraddr);
    UDP_data datapack;
    memset(&datapack, 0, sizeof(datapack));
    // 打包数据包   请求服务器下载文件
    datapack.SYN = 1;
    strcpy(datapack.name, "客户端");
    strcpy(datapack.data, "请求下载文件");
    datapack.size_num = strlen(datapack.data);
    time_t current_time;
    time(&current_time);
    struct tm *local_time = localtime(&current_time);
    strftime(datapack.time, sizeof(datapack.time), "%m/%d %H:%M:%S", local_time);
    printf(">>>>>|%d|%s|%s|%d|%s|\n", datapack.SYN, datapack.name, datapack.data, datapack.size_num, datapack.time);
    if (-1 == sendto(UDP_fd, &datapack, sizeof(datapack), 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr)))
    {
        ERRLOG("发送失败\n");
        return ;
    }
    printf("发送成功\n");


    char file_name_download[128];
    while (1)
    {
        memset(&datapack, 0, sizeof(datapack));
        // 接收服务器回复   展示服务器发送的全部文件名称
        if (-1 == recvfrom(UDP_fd, &datapack, sizeof(datapack), 0, (struct sockaddr *)&serveraddr, &addrlen))
        {
            printf("数据接收失败\n");
        }
        printf(">>>>>|%d|%s|%s|%d|%s|\n", datapack.SYN, datapack.name, datapack.data, datapack.size_num, datapack.time);

        if (1 == datapack.SYN) // 接收文件名
        {
            char buf[256];
            strncpy(buf, datapack.data, sizeof(buf) - 1);
            buf[255] = '\0';
            for (size_t i = 0; i < strlen(buf); i++)
            {
                if (buf[i] == '-')
                {
                    puts(" ");
                }
                else
                {
                    printf("%c", buf[i]);
                }
            }

            memset(&datapack, 0, sizeof(datapack));

            // 打包数据包  请求服务将我需要下载的文件 发送给我

            printf("请输入需要下载的文件名称：\n");
            scanf("%s", file_name_download);
            datapack.SYN = 2;
            strcpy(datapack.data, file_name_download);
            datapack.size_num = 0;
            time_t current_time;
            time(&current_time);
            struct tm *local_time = localtime(&current_time);
            strftime(datapack.time, sizeof(datapack.time), "%m/%d %H:%M:%S", local_time);
            strcpy(datapack.name, "客户端");
            printf(">>>>>|%d|%s|%s|%d|%s|\n", datapack.SYN, datapack.name, datapack.data, datapack.size_num, datapack.time);
            if (-1 == sendto(UDP_fd, &datapack, sizeof(datapack), 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr)))
            {
                ERRLOG("发送失败\n");
                return ;
            }
        }

        else if (3 == datapack.SYN)
        {
            // 打开文件 准备接收服务器发送的内容

            static char file_name[256];
            strcpy(file_name, "my_file/");
            strcat(file_name, file_name_download);

            if (0 == strcmp("文件发送完成", datapack.data))
            {
                // 丢包 重发

                break;
            }
            else
            { // 将服务器发送的内容写入文件
                printf("即将打开的文件名 %s\n", file_name);
                FILE *fp = fopen(file_name, "a");
                fseek(fp, 0, SEEK_END);

                fwrite(datapack.data, 1, strlen(datapack.data), fp);
                fclose(fp);
            }

            datapack.SYN = 2;
            time_t current_time;
            time(&current_time);
            struct tm *local_time = localtime(&current_time);
            strftime(datapack.time, sizeof(datapack.time), "%m/%d %H:%M:%S", local_time);
            strcpy(datapack.name, "客户端");

            memset(&datapack.data, 0, sizeof(datapack.data));
            strcpy(datapack.data, file_name_download);
            printf(">>>>>|%d|%s|%s|%d|%s|\n", datapack.SYN, datapack.name, datapack.data, datapack.size_num, datapack.time);
            if (-1 == sendto(UDP_fd, &datapack, sizeof(datapack), 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr)))
            {
                ERRLOG("发送失败\n");
                return ;
            }
        }
    }

}

   
    

// 5、关闭套接字
void UDP_close(int UDP_fd)
{
    close(UDP_fd);
    return ;
}